package com.sprocomm.agingtest.camera;

import com.sprocomm.agingtest.BaseActivity;
import com.sprocomm.agingtest.Config;
import com.sprocomm.agingtest.R;
import com.sprocomm.agingtest.Tools;

import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.annotation.RequiresApi;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

@RequiresApi(api = Build.VERSION_CODES.M)
public class FlashTest extends BaseActivity {
    private TextView tvBack, tvFront, tvBackAlways, tvFrontAlways;
    private Button btnBack, btnFront, btnBackAlways, btnFrontAlways;

    /**
     * 后flash测试结果
     */
    private static boolean BACK_RESULT = false;
    private static boolean BACK_RESULT_ALWAYS = false;
    /**
     * 前flash测试结果
     */
    private static boolean FRONT_RESULT = false;
    private static boolean FRONT_RESULT_ALWAYS = false;
    //后flash已经测试的次数
    private int flashBackTimes = 0;
    //前flash已经测试的次数
    private int flashFrontTimes = 0;
    /**
     * flash工作的时间
     */
    private static int FLASH_TIME = 200;
    /**
     * flash通过的标准次数
     */
//    private static int TIMES_PASS = 20000;
//    private static long Config.FLASH_TEST_TIME = 96*3600*1000;
    /**
     * 前后flash的状态
     */
    private boolean isBackTorch = false;
    private boolean isFrontTorch = false;
    /**
     * 是否正在测试改flash
     */
    private boolean isBackTest = false;
    private boolean isFrontTest = false;
    private boolean isBackAlwayTest = false;
    private boolean isFrontAlwayTest = false;
    /**
     * 是否拥有前后flash
     */
    private boolean hasBackFlash = true;
    private boolean hasFrontFlash = true;
    /**
     * 当前正在测试的cameraID
     */
    private String cameraId = "0";

    private CameraManager cameraManager;
    private Handler handler = new Handler();
    private Runnable runnable = new Runnable() {
        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void run() {
            if (cameraManager == null) {
                Toast.makeText(FlashTest.this, "Test failed, please fail this test", Toast.LENGTH_LONG).show();
                return;
            }
            try {
                if (isBackTest) {
                    if (isBackTorch) {
                        cameraManager.setTorchMode(cameraId, false);
                        flashBackTimes++;
                        tvBack.setText(flashBackTimes + "/" + Config.FLASH_TEST_TIMES);
                    } else {
                        cameraManager.setTorchMode(cameraId, true);
                    }

                    if (flashBackTimes >= Config.FLASH_TEST_TIMES) {
                        flashBackTimes = 0;
                        BACK_RESULT = true;
                        setButtonClickable(true);
                        //btnBack.setEnabled(true);
                        handler.removeCallbacks(runnable);
                        tvBack.setText("PASS");
                        checkPassBtn();
                        return;
                    }
                } else if (isFrontTest) {
                    if (isFrontTorch) {
                        cameraManager.setTorchMode(cameraId, false);
                        flashFrontTimes++;
                        tvFront.setText(flashFrontTimes + "/" + Config.FLASH_TEST_TIMES);
                    } else {
                        cameraManager.setTorchMode(cameraId, true);
                    }
                    if (flashFrontTimes >= Config.FLASH_TEST_TIMES) {
                        flashFrontTimes = 0;
                        FRONT_RESULT = true;
                        setButtonClickable(true);
                        //btnFront.setEnabled(true);
                        handler.removeCallbacks(runnable);
                        tvFront.setText("PASS");
                        checkPassBtn();
                        return;
                    }
                }
            } catch (CameraAccessException e) {
                e.printStackTrace();
                Toast.makeText(FlashTest.this, "The test failed. Please try again", Toast.LENGTH_LONG).show();
                if (isBackTest) {
                    BACK_RESULT = false;
                } else if (isFrontTest) {
                    FRONT_RESULT = false;
                }
                checkPassBtn();
                setButtonClickable(true);
            } catch (IllegalArgumentException e) {
                //捕获安卓系统可能存在的异常Camera "1" does not have a flash unit
                //保证程序不放生crash
                e.printStackTrace();
                Toast.makeText(FlashTest.this, "The test failed. Please try again", Toast.LENGTH_LONG).show();
//                if (isBackTest) {
//                    BACK_RESULT = false;
//                } else if (isFrontTest) {
//                    FRONT_RESULT = false;
//                }
//                checkPassBtn();
//                setButtonClickable(true);
                Tools.exitFail(FlashTest.this);
            }

            handler.postDelayed(runnable, FLASH_TIME);
        }
    };

    private CameraManager.TorchCallback torchCallback;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flash_test);

        initView();

        //设置亮度
        //Tools.setScreenBrightness(WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL, this);
        cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);

        torchCallback = new CameraManager.TorchCallback() {
            @Override
            public void onTorchModeUnavailable(String cameraId) {
                super.onTorchModeUnavailable(cameraId);
            }

            @Override
            public void onTorchModeChanged(String cameraId, boolean enabled) {
                super.onTorchModeChanged(cameraId, enabled);
                if (cameraId.equals(getBackCameraId())) {
                    isBackTorch = enabled;
                } else if (cameraId.equals(getFrontCameraId())) {
                    isFrontTorch = enabled;
                }
            }
        };
        cameraManager.registerTorchCallback(torchCallback, null);

        checkFlash();

    }

    private void initView() {
        tvBack = (TextView) findViewById(R.id.tv_back_flash_times);
        tvFront = (TextView) findViewById(R.id.tv_front_flash_times);
        btnBack = (Button) findViewById(R.id.btn_back);
        btnFront = (Button) findViewById(R.id.btn_front);

        btnBackAlways = (Button) findViewById(R.id.btn_back_always);
        btnFrontAlways = (Button) findViewById(R.id.btn_front_always);
        tvBackAlways = (TextView) findViewById(R.id.tv_back_flash_times_always);
        tvFrontAlways = (TextView) findViewById(R.id.tv_front_flash_times_always);
    }

    /**
     * 检查闪光灯是否存在
     * TODO 判断方法存在问题
     */
    private void checkFlash() {
        if (getFrontCameraId() == null) {
            Toast.makeText(FlashTest.this, "No front flash or damage", Toast.LENGTH_LONG).show();
            btnFront.setText("No Front Flash");
            btnFront.setEnabled(false);
            btnFrontAlways.setText("No Front Flash");
            btnFrontAlways.setEnabled(false);
            FRONT_RESULT = true;
            FRONT_RESULT_ALWAYS = true;
            hasFrontFlash = false;
        } else if (getBackCameraId() == null) {
            Toast.makeText(FlashTest.this, "No flash or damage", Toast.LENGTH_LONG).show();
            btnBack.setText("No Back Flash");
            btnBack.setEnabled(false);
            btnBackAlways.setText("No Back Flash");
            btnBackAlways.setEnabled(false);
            BACK_RESULT = true;
            BACK_RESULT_ALWAYS = true;
            hasBackFlash = false;
        }
    }

    public void startBack(View view) {
        isBackTest = true;
        isFrontTest = false;
        cameraId = getBackCameraId();
        handler.post(runnable);
        setButtonClickable(false);
    }

    public void startFront(View view) {
        isBackTest = false;
        isFrontTest = true;
        cameraId = getFrontCameraId();
        handler.post(runnable);
        setButtonClickable(false);
    }

    public void startBackAlways(View view) {
        isBackTest = false;
        isFrontTest = false;
        isFrontAlwayTest = false;
        isBackAlwayTest = true;
        try {
            cameraId = getBackCameraId();
            cameraManager.setTorchMode(cameraId, true);
            countDownTimer.start();
        } catch (CameraAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            //捕获安卓系统可能存在的异常Camera "1" does not have a flash unit
            //保证程序不放生crash
            e.printStackTrace();
            Toast.makeText(FlashTest.this, "The test failed. Please try again", Toast.LENGTH_LONG).show();
            Tools.exitFail(this);
        }
        setButtonClickable(false);
    }

    public void startFronAlways(View view) {
        isBackTest = false;
        isFrontTest = false;
        isBackAlwayTest = false;
        isFrontAlwayTest = true;
        try {
            cameraId = getFrontCameraId();
            cameraManager.setTorchMode(cameraId, true);
            countDownTimer.start();
        } catch (CameraAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            //捕获安卓系统可能存在的异常Camera "1" does not have a flash unit
            //保证程序不放生crash
            e.printStackTrace();
            Toast.makeText(FlashTest.this, "The test failed. Please try again", Toast.LENGTH_LONG).show();
            Tools.exitFail(this);
        }
        setButtonClickable(false);
    }

    /**
     * 倒计时成员
     */
    private CountDownTimer countDownTimer = new CountDownTimer(Config.FLASH_TEST_TIME, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            if (isBackAlwayTest) {
                //SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
                tvBackAlways.setText("Remaining time\n" + longTime2String(millisUntilFinished));
            } else if (isFrontAlwayTest) {
                tvFrontAlways.setText("Remaining time\n" + longTime2String(millisUntilFinished));
            }

        }

        @Override
        public void onFinish() {
            if (isBackAlwayTest) {
                tvBackAlways.setText("PASS");
                BACK_RESULT_ALWAYS = true;
            } else if (isFrontAlwayTest) {
                tvFrontAlways.setText("PASS");
                FRONT_RESULT_ALWAYS = true;
            }
            try {
                cameraManager.setTorchMode(cameraId, false);
                setButtonClickable(true);
                checkPassBtn();
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }

        }
    };


    @Override
    protected void onDestroy() {
        Tools.logE("onDestroy");
        //Tools.setScreenBrightness(WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE, this);
        handler.removeCallbacks(runnable);
        cameraManager.unregisterTorchCallback(torchCallback);
        try {
            if (isBackTorch) {
                cameraManager.setTorchMode(getBackCameraId(), false);
            } else if (isFrontTorch) {
                cameraManager.setTorchMode(getFrontCameraId(), false);
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        cameraManager = null;
        super.onDestroy();
    }


    private String getBackCameraId() {
        String[] ids = new String[0];
        try {
            ids = cameraManager.getCameraIdList();
            for (String id : ids) {
                CameraCharacteristics c = cameraManager.getCameraCharacteristics(id);
                Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
                Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
                if (flashAvailable != null && flashAvailable
                        && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
                    return id;
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getFrontCameraId() {
        try {
            String[] ids = cameraManager.getCameraIdList();
            for (String id : ids) {
                CameraCharacteristics c = cameraManager.getCameraCharacteristics(id);
                Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
                Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
                if (flashAvailable != null && flashAvailable
                        && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
                    return id;
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void setButtonClickable(boolean clickable) {
        if (hasBackFlash) {
            btnBack.setEnabled(clickable);
            btnBackAlways.setEnabled(clickable);
        }
        if (hasFrontFlash) {
            btnFront.setEnabled(clickable);
            btnFrontAlways.setEnabled(clickable);
        }
    }

    private void checkPassBtn() {
        if (BACK_RESULT && FRONT_RESULT) {
            setPassBtnEnable(true);
            setPassBtnText("pass anyway");
            return;
        }
        if (BACK_RESULT_ALWAYS && FRONT_RESULT_ALWAYS) {
            setPassBtnEnable(true);
            setPassBtnText("pass anyway");
            return;
        }
        if (BACK_RESULT && FRONT_RESULT && BACK_RESULT_ALWAYS && FRONT_RESULT_ALWAYS) {
            setPassBtnEnable(true);
            setPassBtnText("pass anyway");
        } else {
            setPassBtnEnable(true);
        }
    }

    private String longTime2String(long time) {
        long second = time / 1000;
        int h = Integer.parseInt(String.valueOf(second / 3600));
        int m = Integer.parseInt(String.valueOf((second % 3600) / 60));
        int s = Integer.parseInt(String.valueOf(second % 60));
        return h + ":" + m + ":" + s;
    }


}
